﻿using System;

namespace ApiScanner.Core
{
    internal class StoreEvent
    {
        /// <summary>
        /// DAV:displayname of event registration
        /// </summary>
        public string Name;

        /// <summary>
        /// DAV:href path of event
        /// </summary>
        public Uri Path;

        /// <summary>
        /// http://schemas.microsoft.com/exchange/events/Criteria 
        /// </summary>
        /// <remarks>
        /// The Criteria field applies to the OnSave Method, the OnSyncSave Method, and the OnSyncDelete Method. 
        /// The Criteria field is optional. If the Criteria field is set, then the event sink will be notified 
        /// if the criteria's SQL WHERE conditions are satisfied. The following conditions are supported: 
        /// AND, OR, NOT, EXISTS 
        /// Use of the CONTAINS Predicate and the LIKE Predicate in this binding property is not supported. 
        /// Use double quotation marks for property names and single quotation marks for strings to be evaluated. Custom properties must be explicitly cast to the proper type. For example: 
        /// "WHERE cast($"MyNumber"$ as 'i4')<>15" 
        /// The WHERE Clause Criteria is limited to information in the item. It is not possible to specify conditions on data outside of this item. (The "$" character escapes the double quotation marks.) 
        /// </remarks>
        /// <example>
        /// WHERE "DAV:ishidden" = FALSE and "DAV:contentclass" = 'urn:content-classes:item' 
        /// WHERE "status"='active' AND "DAV:displayname" = 'mjp.eml'"
        /// WHERE "status"= 'active' AND "DAV:displayname"='mjp.eml' AND "urn:schemas:mailheader:subject" = 'Expense Report' AND "DAV:ishidden" = FALSE AND "urn:schemas:httpmail:has attachment" = TRUE
        /// </example>
        public string Criteria;

        /// <summary>
        /// http://schemas.microsoft.com/exchange/events/Enabled 
        /// </summary>
        public bool Enabled;

        /// <summary>
        /// http://schemas.microsoft.com/exchange/events/EventMethod 
        /// </summary>
        /// <remarks>
        /// OnSave, OnDelete, OnSyncSave, OnSyncDelete, OnMDBStartup, OnMDBShutdown, OnTimer
        /// </remarks>
        public string EventMethod;

        /// <summary>
        /// http://schemas.microsoft.com/exchange/events/MatchScope
        /// </summary>
        /// <remarks>
        /// For synchronous events this value can be: "ANY", "DEEP", or "SHALLOW".
        /// For asynchronous events this value can be: "DEEP" or "EXACT".
        /// The default value for this property is "Exact".
        /// The following table defines the scope values:
        /// Scope Value Definition 
        /// "ANY" Within the scope of the MDB. 
        /// "DEEP" Standard deep traversal. 
        /// "EXACT" The folder only. 
        /// "SHALLOW" The folder only. 
        /// "DEEP" can only be registered at the top-level folder.
        /// </remarks>
        public string MatchScope;

        /// <summary>
        /// http://schemas.microsoft.com/exchange/events/Priority 
        /// </summary>
        /// <remarks>
        /// Event sinks are notified in priority order, with 0 being the highest priority. 
        /// Event registrations with the same priority are notified in an indeterminate order. 
        /// This property is only valid for synchronous event sink bindings. No order is implied for 
        /// notifications of asynchronous events or system events.
        /// </remarks>
        public long Priority;

        /// <summary>
        /// http://schemas.microsoft.com/exchange/events/ScriptUrl 
        /// </summary>
        /// <example>
        /// d:\onsavescript.vbs"
        /// "file://./backofficestorage/domain.example.com/public folders/common/scripts/myonsavescript1.vbs"
        /// </example>
        public Uri ScriptUrl;

        /// <summary>
        /// http://schemas.microsoft.com/exchange/events/SinkClass 
        /// </summary>
        public string SinkClass;

        /// <summary>
        /// http://schemas.microsoft.com/exchange/events/TimerExpiryTime 
        /// </summary>
        public string TimerExpiryTime;

        /// <summary>
        /// http://schemas.microsoft.com/exchange/events/TimerInterval 
        /// </summary>
        public int TimerInterval;

        /// <summary>
        /// http://schemas.microsoft.com/exchange/events/TimerStartTime 
        /// </summary>
        public string TimerStartTime;

        /// <summary>
        /// Dump of registry and fileinfo related 
        /// </summary>
        public string EncodedComClassEventInfo;

        /// <summary>
        /// Prints the store event fields to a CSV string.
        /// </summary>
        /// <remarks>
        /// Currently any int or bool value that is unset will print as 0/false. Is that ok, or do we
        /// need to null these out?
        /// </remarks>
        public string ToCsvString(MdbType mdbType, string serialNumber)
        {
            string result = (mdbType == MdbType.Private) ? "Private mailbox," : "Public folder,";
            result += serialNumber + ",";

            result += this.Name + "," + this.Path + "," + this.Criteria + "," + this.Enabled + ","
                      + this.EventMethod + "," + this.MatchScope + "," + this.Priority + "," + this.ScriptUrl + ","
                      + this.TimerExpiryTime + "," + this.TimerInterval + "," + this.TimerStartTime + ","
                      + this.EncodedComClassEventInfo + "\n";

            return result;
        }

        /// <summary>
        /// Creates a fake event for testing.
        /// </summary>
        public static StoreEvent CreateTestEvent()
        {
            StoreEvent storeEvent = new StoreEvent();

            storeEvent.Criteria = "criteria";
            storeEvent.Enabled = true;
            storeEvent.EncodedComClassEventInfo = "encoded com class event info";
            storeEvent.EventMethod = "OnSave";
            storeEvent.MatchScope = "match scope";
            storeEvent.Name = "my store event";
            storeEvent.Path = new Uri("http://microsoft.com");
            storeEvent.Priority = 1;
            storeEvent.ScriptUrl = new Uri("http://microsoft.com/script.js");
            storeEvent.TimerExpiryTime = "10";
            storeEvent.TimerInterval = 1;
            storeEvent.TimerStartTime = "0";

            return storeEvent;
        }
    }
}